import { _decorator, Component, Node, Animation } from "cc"
import { GlobalData } from "../GlobalData"
import { util } from "../util/util"
import { sp } from "cc"
import { constant } from "../framework/constant"
import { Vec3 } from "cc"
import { ClientEvent } from "../framework/ClientEvent"
import { UITransform } from "cc"
import { AudioManager } from "../framework/AudioManager"
import { Tween } from "cc"
import { Monster } from "./Monster"
import { ItemBase } from "./itemBase"
import ResManager from "../framework/ResManager"
import { instantiate } from "cc"
import { Bullet } from "./Bullet"
import { Prefab } from "cc"
import { GameItemHp } from "./GameItemHp"
import { gtPlayable } from "../GtPlayable"
const { ccclass, property } = _decorator

@ccclass("MonsterHero")
export class MonsterHero extends Monster {
  protected goldDrop: number = 0

  protected animation: Animation = null

  protected nAttAckTarget: Node = null

  protected bulletId: number = 0

  protected roleId: number = 0

  protected attackBefore: number = 0
  start(): void {
    super.start()
    this.initNodeHp()
  }

  init(monsterType: string) {
    this.isEnemy = true
    const data: any = GlobalData.instance.monsterData[monsterType]
    this.maxHp = data.hp
    this.currHp = this.maxHp
    this.sName = data.name
    this.currAttack = data.attack
    this.attackScope = data.attackScope
    this.beAttackScope = data.beAttackScope
    this.moveSpeed = constant.monsterMoveBoss[GlobalData.instance.curLevel]
    this.attackSpeed = data.attackSpeed
    this.goldDrop = data.goldDrop
    this.bulletId = data.bulletId
    this.roleId = data.roleId
    this.node.scaleX = -Math.abs(this.node.scaleX)
    this.attackBefore = 0.4
  }
  protected initNodeHp() {
    const nodeHpParent = GlobalData.instance.nodeGame.getChildByName("hpParent")
    let prefab = ResManager.instance.getRes("prefabs/game/gameObject/nodeHp", Prefab)
    if (prefab) {
      this.nodeHp = instantiate(prefab)
      nodeHpParent.addChild(this.nodeHp)
      const gameHp: GameItemHp = this.nodeHp.getComponent(GameItemHp)
      gameHp.init(this.node, this.isEnemy)
    }
  }

  update(deltaTime: number) {
    if (!this.node || !this.node.isValid || this.isDie) return
    if (!GlobalData.instance.getGameState()) {
      this.playAnimation(constant.PLAYER_ANI_TYPE.IDLE, true)
      return
    }
    /**攻击前奏 */
    if (this.isAttackAction) {
      this.numAttackBefore += deltaTime
      if (this.numAttackBefore >= this.attackBefore) {
        this.isAttackAction = false
        this.onAttackTarget(this.posAttack)
        this.posAttack = null
      }
    }

    /**攻击cd */
    if (this.isAttackCd) {
      this.numAttackCd += deltaTime
      if (this.numAttackCd >= this.getAttackSpeed()) {
        this.isAttackCd = false
        this.endAttackTarget()
      }
      return
    }

    if (this.node.positionX > this.attackScope) {
      this.node.positionX -= this.getCurrMoveSpeed() * deltaTime
      this.playAnimation(constant.MONSTER_ANI_TYPE.WALK, true)
    } else {
      this.nAttAckTarget = this.findTargetToAttack()
      if (this.nAttAckTarget) {
        //进入攻击范围
        this.isAttackCd = true
        this.playAnimation(constant.MONSTER_ANI_TYPE.ATTACK, false)
        this.startAttAckTarget()
      }
    }
  }

  protected getCurrMoveSpeed() {
    let speed = constant.monsterMoveBoss[GlobalData.instance.curLevel]
    if (0 == GlobalData.instance.numMonsterSlow) {
      speed = 0.2 * speed
    } 
    // else if (1 == GlobalData.instance.numMonsterSlow) {
    //   speed = 0.8 * speed
    // }
    return constant.SPEED_SCALE * speed
  }

  // 到达攻击点，寻找最近的目标
  protected findTargetToAttack(): Node {
    if (GlobalData.instance.arrNodePlayerRole.length > 0) {
      let disAttack: number = 0
      let nodeAttack: Node = null
      for (let i: number = 0; i < GlobalData.instance.arrNodePlayerRole.length; i++) {
        const node = GlobalData.instance.arrNodePlayerRole[i]
        const dis = util.getTwoPosXYLength(this.node.positionX, this.node.positionY, node.positionX, node.positionY)
        if (disAttack === 0 || disAttack > dis) {
          disAttack = dis
          nodeAttack = node
        }
      }
      return nodeAttack
    }
    return null
  }

  protected animationName: string = ""
  protected callbackAnimate: (...args: any[]) => void
  /**
   * 播放玩家帧动画
   */
  public playAnimation(animationName: string, loop: boolean = true, callback?: (...args: any[]) => void) {
    // return
    if (this.animationName == animationName && loop) return
    this.animationName = animationName
    if (this.callbackAnimate) this.callbackAnimate = null
    this.animation.play(animationName)
    if (!loop) {
      if (callback) {
        this.callbackAnimate = callback
        this.animation.once(Animation.EventType.FINISHED, this.callbackAnimate, this)
      }
    }
  }

  protected posAttack: Vec3 = null
  startAttAckTarget() {
    this.playAnimation(constant.PLAYER_ANI_TYPE.ATTACK, false, () => {
      this.playAnimation(constant.MONSTER_ANI_TYPE.IDLE, true)
    })
    this.posAttack = this.nAttAckTarget.getPosition()
    this.isAttackAction = true
    this.isAttackCd = true
    this.numAttackBefore = 0
    this.numAttackCd = 0
  }

  onAttackTarget(pos: Vec3) {
    // AudioManager.instance.playEffect("sm_launch1")
    const bulletId = this.bulletId
    const strBullet: string = `prefabs/game/bullet/bullet${bulletId}`
    ResManager.instance.loadRes(strBullet, Prefab, (error, prefab) => {
      if (prefab) {
        if (this.nAttAckTarget && this.nAttAckTarget.isValid) {
          pos = this.nAttAckTarget.getPosition()
        }
        let node = instantiate(prefab)
        node.scaleY = -node.scaleY
        let bullet: Bullet = node.addComponent(Bullet)
        if (bullet) {
          const selfPos = this.node.getPosition()
          const angle = util.getTwoPosXYAngle(selfPos, pos)
          node.angle = angle
          const distance = 50
          const angleInRadians = node.angle * (Math.PI / 180) // 将角度转换为弧度
          const dx = Math.cos(angleInRadians) * distance // 计算 x 方向的移动
          const dy = Math.sin(angleInRadians) * distance // 计算 y 方向的移动
          node.setPosition(this.node.positionX + dx, this.node.positionY + dy)
          bullet.initTarget(bulletId, this.currAttack, this.isEnemy)
        }
        let bulletParent: Node = GlobalData.instance.nodeGame.getChildByName("bulletParent")
        bulletParent.addChild(node)
      }
    })
  }

  endAttackTarget() {
    this.isAttackCd = false
    this.playAnimation(constant.PLAYER_ANI_TYPE.IDLE, true)
  }

  protected changeHp(value: number) {
    if (!GlobalData.instance.isGameStart || GlobalData.instance.isGameOver || GlobalData.instance.isGamePause) return
    value = Math.round(value)
    ClientEvent.emit("onInitDamage", this.node.getPosition(), value)

    if (0 == GlobalData.instance.curLevel && this.node.positionX <= this.attackScope) {
      value = this.maxHp * 0.2
      this.currHp -= value
    } else if (1 == GlobalData.instance.curLevel && this.node.positionX <= this.attackScope) {
      value = this.maxHp * 0.1
      this.currHp -= value
    }
    this.onChangeHp(this.currHp)
  }
  protected onChangeHp(hp: number) {
    // return
    if (!this.maxHp) return
    this.currHp = hp
    if (this.currHp > this.maxHp) {
      this.currHp = this.maxHp
    }
    const gameHp: GameItemHp = this.nodeHp.getComponent(GameItemHp)
    gameHp.updateItemHp(this.currHp, this.maxHp)
    if (this.currHp <= 0) {
      this.currHp = 0
      this.isDie = true
    }
  }

  protected showDie(): void {
    this.nodeHp.destroy()
    gtPlayable.sendActionScene("scene3_view",3,"用户击杀英雄型怪物成功")
    const indexOf = GlobalData.instance.arrNodeMonster.indexOf(this.node)
    if (indexOf !== -1) {
      GlobalData.instance.arrNodeMonster.splice(indexOf, 1)
      ClientEvent.emit("onMonsterDie", this.goldDrop, this.node.getPosition())
      ClientEvent.emit("onInitNewRoleDebris", this.roleId, this.node.getPosition())
    }
    this.playAnimation(constant.MONSTER_ANI_TYPE.DIE, false)
    new Tween(this.node)
      .to(0.3, { alpha: 0 })
      .call(() => {
        this.onDestroySelf()
      })
      .start()
    // AudioManager.instance.playEffect("sm_monster_die")
  }

  onBeAttack(attack: number, nodeBeAttack?: Node): void {
    ClientEvent.emit("onMonsterBeAttackEffect", new Vec3(this.node.positionX, this.node.positionY))
    if (this.currHp > attack) {
      ClientEvent.emit("onInitMoney", attack, this.node.getPosition())
    }
    super.onBeAttack(attack, nodeBeAttack)
  }

  protected onDestroySelf(): void {
    this.node.destroy()
    this.destroy()
  }
}
